//
//  KVOViewController.m
//  ObjcGoNew
//
//  Created by 邢伟新 on 2021/4/27.
//

#import "KVOViewController.h"
#import "NSObject+KVO.h"
#import "GJPerson.h"
#import <Masonry/Masonry.h>

@interface KVOViewController ()

@property(nonatomic,strong)GJPerson *person;
@property(nonatomic,strong)GJPerson *person1;

@end

@implementation KVOViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
   
    self.title = @"KVO";
    self.view.backgroundColor = [UIColor whiteColor];
    
    
    self.person = [[GJPerson alloc]init];
    self.person.name = @"小新";
    self.person.age = @15;
    
    self.person1 = [[GJPerson alloc]init];
    self.person1.name = @"小明";
    self.person1.age = @20;
    

    UIButton *barrierButton = [UIButton buttonWithType:(UIButtonTypeCustom)];
    [barrierButton setTitle:@"修改年龄" forState:(UIControlStateNormal)];
    [barrierButton addTarget:self action:@selector(buttonAction:) forControlEvents:(UIControlEventTouchUpInside)];
    barrierButton.backgroundColor =[UIColor purpleColor];
    barrierButton.tag = 1001;
    [self.view addSubview:barrierButton];
    [barrierButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(15);
        make.right.mas_equalTo(-15);
        make.height.mas_equalTo(50);
        make.top.mas_equalTo(150);
    }];
    
    
    [self addKVONormal];
//    [self addKVOzidingyi];
    
  
    
    
  
}








#pragma mark - kvo的回调方法(系统提供的回调方法)
//keyPath:属性名称
//object:被观察的对象
//change:变化前后的值都存储在change字典中
//context:注册观察者的时候,context传递过来的值
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    id oldName = [change objectForKey:NSKeyValueChangeOldKey];
//    NSLog(@"oldName----------%@",oldName);
    id newName = [change objectForKey:NSKeyValueChangeNewKey];
//    NSLog(@"newName-----------%@",newName);
    
    NSLog(@"%@对象%@属性发生了改变,新值为%@,旧的值为%@",object,keyPath,newName,oldName);

}

-(void)dealloc{
    [self removeObserver:self forKeyPath:@"age"];
    [self wx_removeObserver:self forKeyPath:@"age"];
    
}


- (IBAction)buttonAction:(UIButton *)sender {
    
    self.person.age = [NSNumber numberWithInteger:100];
    self.person1.age = [NSNumber numberWithInteger:102];
}


#pragma mark - 正常监听
-(void)addKVONormal{
    
    //监听之前
    NSLog(@"监听前----person = %p,person1 = %p",[self.person methodForSelector:@selector(setAge:)],[self.person1 methodForSelector:@selector(setAge:)]);
    
    [self.person addObserver:self forKeyPath:@"age" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:nil];
    
    NSLog(@"监听后----person = %p,person1 = %p",[self.person methodForSelector:@selector(setAge:)],[self.person1 methodForSelector:@selector(setAge:)]);
    
    //手动触发kvo
    [self.person willChangeValueForKey:@"age"];
    [self.person didChangeValueForKey:@"age"];
   
    
}

#pragma mark -自定义监听
-(void)addKVOzidingyi{
    
    [self.person wx_addObserver:self keyPath:@"age" withBlock:^(id OberverObject, NSString *observerKey, id oldValue, id newValue) {
        
        NSLog(@"OberverObject----%@",OberverObject);
        NSLog(@"observerKey----%@",observerKey);
        NSLog(@"oldValue----%@",oldValue);
        NSLog(@"newValue----%@",newValue);
        
    }];
    
}

/*
 ##KVO实现原理
 1.runtime动态创建Person_A类,Person_A类是Person类的子类
 2.person对象的isa指针指向Person_A
 3.Person_A有自己的实现方法,set方法实现内部会顺序调用willChangeValueForKey方法、原来的setter方法实现、didChangeValueForKey方法，而didChangeValueForKey方法内部又会调用监听器的observeValueForKeyPath:ofObject:change:context:监听方法。
 
 
 */



@end
